<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // Array 类型为每个数组定义了 forEach() 原型方法，
        // 使用该方法可以为数组执行迭代操作。具体说明如下
        // array.forEach(callbackfn[, thisArg]);
        // 参数说明如下：
        // array：一个数组对象。
        // callbackfn：必需参数，最多可以接收三个参数的函数。forEach 将为数组中的每个元素调用 callbackfn 函数一次。
        // thisArg 可选可选参数。当执行回调函数 callback 时，用作 this 的值。
        // 对于数组中出现的每个元素，forEach 方法都会调用 callbackfn 函数一次，采用升序索引顺序，但不会为数组中空元素调用回调函数。
        // 除了数组对象之外，forEach 方法还可以用于有 length 属性且具有已按数字编制索引的属性名的任何对象，如关联数组对象、Arguments 等。

        // 回调函数语法如下：
        // funtion callbackfn(value, index, array);
        // 最多可以使用三个参数来声明回调函数。 回调函数的参数说明如下。
        // value： 数组元素的值。
        // index： 数组元素的数字索引。
        // array： 包含该元素的数组对象。

        // forEach 方法不直接修改原始数组，但回调函数可能会修改它。


        // 使用 forEach 迭代数组 a，然后把每个元素的值和下标索引输出显示
        // function f(value, index, array) {
        //     console.log("a[" + index + "] = " + value);
        // }
        // var a = ['a', 'b', 'c'];
        // a.forEach(f);

        // 使用 forEach 迭代数组 a， 然后计算数组元素的和并输出。
        // var a = [1, 2, 3],
        //     sum = 0;
        // a.forEach(function(value) {
        //     sum += value;
        // })
        // console.log(sum);


        // 使用 forEach() 方法的第二个参数， 该参数为回调函数的 this 传递对象。 当迭代数组过程中， 先读取数组元素的值， 然后改写它的值
        // var obj = {
        //     f1: function(value, index, array) {
        //         console.log("a[" + index + "] = " + value);
        //         array[index] = this.f2(value);
        //     },
        //     f2: function(x) {
        //         return x * x;
        //     }
        // };
        // var a = [12, 26, 36];
        // a.forEach(obj.f1, obj);
        // console.log(a); //返回[144, 676, 1296]


        //          使用 keys 遍历对象键名
        // keys() 是 Object 的静态函数， 专门用来遍历对象获取键名。 
        // Object.keys() 函数的参数是一个对象， 返回一个数组， 
        // 元素是该对象所以本地属性名。 如果使用该函数迭代数组， 可以汇集数组的所有元素下标值。


        // 实例1
        // 下面代码直观的比较了 keys 迭代对象和数组的不同。
        // var o = {
        //     a: "A",
        //     b: "B",
        //     c: "C"
        // };
        // console.log(Object.keys(o)); //["a","b","c"]
        // var a = ["A", "B", "C"];
        // console.log(Object.keys(a)); //["0","1","2"]
        // keys 功能比较专一，应用范围比较窄，但是执行效率比较高。


        // 实例2
        // 除了获取键名集合外，使用keys还可以间接统计对象的长度
        // var o = {
        //     a: "A",
        //     b: "B",
        //     c: "C"
        // };
        // console.log(Object.keys(o).length); //返回3
        // var a = ["A", "B", "C"];
        // console.log(Object.keys(a).length); //返回3
        // Object 类型没有定义 length 原型属性，可以利用 keys 方法获取对象的长度


        // Object 还有一个类似的静态函数： getOwnPropertyNames(), 与 keys 用法相同， 
        // 参数都是对象， 返回值都是一个数组， 数组元素都是属性名。 
        // 不同点： keys 仅能迭代本地、 可枚举的属性， 
        // getOwnPropertyNames 可以迭代所有本地属性。

        // var o = {
        //     a: "A",
        //     b: "B",
        //     c: "C"
        // };
        // console.log(Object.keys(o)); //返回["a","b","c"]
        // console.log(Object.getOwnPropertyNames(o)); //返回["a","b","c"]
        // var a = ["A", "B", "C"];
        // console.log(Object.keys(a)); //返回["0","1","2"]
        // console.log(Object.getOwnPropertyNames(a)); //返回["0","1","2","length"]

        // 数组的 length 是不可枚举的属性，所以仅能在 Object.getOwnPropertyNames 返回结果中看到。因此，要快速迭代数组，可以使用 keys 方法。
    </script>
</body>

</html>